package main
import "fmt"

/*
  命令模式
  将命令包裹在对象中，并传给调用对象。调用对象寻找处理该命令的合适对象，并把该命令传给合适的对象，该对象执行命令。
  例子
  首先创建作为命令的接口 Order，然后创建作为请求的 Stock 类。
  实体命令类 BuyStock 和 SellStock，实现了 Order 接口，将执行实际的命令处理。
  创建作为调用对象的类 Broker，它接受订单并能下订单
*/


//创建一个命令接口
type Order interface {
	Execute()
}
//创建一个请求类
type Stock struct {
	name string
	quantity int
}

func (s *Stock) buy()  {
    fmt.Println(s.name , " buy " , s.quantity)
}

func (s *Stock) sell()  {
	fmt.Println(s.name , " sell " , s.quantity)
}

//实现了 Order 接口的实体类
type BuyStock struct {
	stock *Stock
}

func (b BuyStock) Execute()  {
   b.stock.buy()
}
type SellStock struct {
	stock *Stock
}
func (s SellStock) Execute()  {
    s.stock.sell()
}

//创建命令调用类
type Broker struct {
	orders []Order
}

func (b *Broker) TakeOrder(o Order)  {
	b.orders = append(b.orders,o)
}

func (b *Broker) PlaceOrders()  {
	for _,v := range b.orders  {
		//执行
		v.Execute()
	}
	//清空
	b.orders = []Order{}
}


func main() {
   aStock := &Stock{name:"A",quantity:100}
   bStock := &Stock{name:"B",quantity:100}

   // a buy b sell
   abuy := BuyStock{aStock}
   bbuy := SellStock{bStock}

   //执行命令
   broker := Broker{}
   broker.TakeOrder(abuy)
   broker.TakeOrder(bbuy)

   broker.PlaceOrders()
}
